package ipc;

import java.util.ArrayList;
import java.util.HashMap;

import rddl.EvalException;
import rddl.RDDL.LCONST;
import rddl.RDDL.PVARIABLE_DEF;
import rddl.RDDL.PVARIABLE_STATE_DEF;
import rddl.RDDL.PVAR_NAME;

public class Query{

    public static double extractValue(String s) throws Exception{
    	if( s == null ){
    		throw new RuntimeException("Empty fluent");
    	}
    	s = s.trim();
    	return Double.parseDouble((s.split("\\s+"))[1]);
    }
    
    public static Object query(Simulator simulator, boolean valuepol, int hor, String inst_name) throws RuntimeException{
    	
    	HashMap<String, Boolean> unwind  = new HashMap<String, Boolean>();
    	
    	IPCState thisstate = (IPCState)(simulator.getState());
    	
    	for (PVAR_NAME p : thisstate._alStateNames) {
    		
    		Object def_value = null;
			PVARIABLE_DEF pvar_def = thisstate._hmPVariables.get(p);
			if (!(pvar_def instanceof PVARIABLE_STATE_DEF) ||
				((PVARIABLE_STATE_DEF)pvar_def)._bNonFluent){
				System.err.println("Expected state variable, got nonfluent: " + p);
				System.exit(1);
			}
			def_value = ((PVARIABLE_STATE_DEF)pvar_def)._oDefValue;
			ArrayList<ArrayList<LCONST>> gfluents = null;
 
			try{
				gfluents = thisstate.generateAtoms(p);
			}catch(EvalException e){
				System.err.println("Could not ground " + p);
				System.exit(1);
			}

			for( ArrayList<LCONST> gfluent : gfluents ){
				Object val = (thisstate._state.get(p).get(gfluent));
				boolean value =  ((Boolean)( val == null ? def_value : val )).booleanValue();
				unwind.put(p+gfluent.toString(), value);
			}
    	}
    
    	myDD _spudd = SPUDDer.getDD(inst_name, valuepol , hor);
    	if(_spudd == null ) {
    		throw new RuntimeException("spudd DD is null " + inst_name);
		}

        Object obj = null;
    	double val = 0;
    	try{
    		if( valuepol ){
    			val = extractValue(_spudd.walk(unwind));
				obj = (Object)new Double(val);
    		}
    		else{
    			String act = _spudd.walk(unwind);
    			obj = (Object)act; 
    		}
		}catch(Exception e){
			throw new RuntimeException("could not query non-null spudd object " + inst_name + "\n " + e.toString());
		}
    	
    	return obj;
    }
}